/*****************************************************************************
 * Copyright (c) 2010 -, Anders All rights reserved
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 *  Contact: Anders Uddenberg (anders.uddenberg@gmail.com)
 * 
 *
 ****************************************************************************/
package org.easypr.organizer.client.presenter;

import java.util.ArrayList;

import org.easypr.organizer.client.BackboneServiceAsync;
import org.easypr.organizer.client.event.DisplayInformationEvent;
import org.easypr.organizer.shared.MyContact;
import org.easypr.organizer.shared.MyMeeting;
import org.easypr.organizer.shared.MyUser;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

// TODO: Auto-generated Javadoc
/**
 * The Class MenuPresenter.
 */
public class ContactPresenter implements Presenter {

	/**
	 * Define the interface the view needs to implement.
	 * 
	 * @author Anders
	 */
	public interface Display {
		
		/**
		 * Sets the data.
		 *
		 * @param meetings the new data
		 */
		void setData(ArrayList<MyMeeting> meetings);
		
		/**
		 * Update navigation.
		 *
		 * @param previous the previous
		 * @param next the next
		 */
		void updateNavigation(Integer previous, Boolean next);

		/**
		 * As widget.
		 * 
		 * @return the widget
		 */
		Widget asWidget();
		
		/**
		 * Sets the contact.
		 *
		 * @param contact the new contact
		 */
		void setContact(MyContact contact);
		
		/**
		 * Gets the contact.
		 *
		 * @return the contact
		 */
		MyContact getContact();
		
		/**
		 * Gets the previous link.
		 *
		 * @return the previous link
		 */
		Anchor getPreviousLink();
		
		/**
		 * Gets the next link.
		 *
		 * @return the next link
		 */
		Anchor getNextLink();
		
		/**
		 * Gets the edits the link.
		 *
		 * @return the edits the link
		 */
		Anchor getEditLink();
		
		/**
		 * Gets the delete link.
		 *
		 * @return the delete link
		 */
		Anchor getDeleteLink();
		
		/**
		 * Gets the save edit link.
		 *
		 * @return the save edit link
		 */
		Anchor getSaveEditLink();
		
		/**
		 * Gets the check boxes.
		 *
		 * @return the check boxes
		 */
		ArrayList<CheckBox> getCheckBoxes();
		
		/**
		 * Gets the delete meetings link.
		 *
		 * @return the delete meetings link
		 */
		Anchor getDeleteMeetingsLink();
		
		/**
		 * Gets the last before time.
		 *
		 * @return the last before time
		 */
		int getLastBeforeTime();
		
		/**
		 * Gets the before time.
		 *
		 * @return the before time
		 */
		int getBeforeTime();
		
		/**
		 * Gets the contact email.
		 *
		 * @return the contact email
		 */
		TextBox getContactEmail();
		
		/**
		 * Gets the contact name.
		 *
		 * @return the contact name
		 */
		TextBox getContactName();
		
		/**
		 * Gets the contact workplace.
		 *
		 * @return the contact workplace
		 */
		TextBox getContactWorkplace();
		
		/**
		 * Gets the contact workphone.
		 *
		 * @return the contact workphone
		 */
		TextBox getContactWorkphone();
		
		/**
		 * Gets the contact cellphone.
		 *
		 * @return the contact cellphone
		 */
		TextBox getContactCellphone();
		
		/**
		 * Show user edit.
		 */
		void showUserEdit();
		
		/**
		 * Show user details.
		 */
		void showUserDetails();
	}

	/** The event bus. */
	private final HandlerManager eventBus;
	
	/** The display. */
	private final Display display;
	
	/** The backbone rpc. */
	private BackboneServiceAsync backboneRPC;
	
	
	
	/** The user. */
	private MyUser user;
	
	/** The parts. */
	private String[] parts;
	
	
	/**
	 * Instantiates a new contact presenter.
	 *
	 * @param backboneRPC the backbone rpc
	 * @param eventBus the event bus
	 * @param view the view
	 * @param user the user
	 * @param parts the parts
	 */
	public ContactPresenter(BackboneServiceAsync backboneRPC, HandlerManager eventBus, Display view, MyUser user, String[] parts) {
		this.backboneRPC = backboneRPC;
		this.eventBus = eventBus;
		this.display = view;
		this.user = user;
		this.parts = parts;
	}

	/* (non-Javadoc)
	 * @see org.easypr.organizer.client.presenter.Presenter#go(com.google.gwt.user.client.ui.HasWidgets)
	 */
	@Override
	public void go(HasWidgets container) {
		container.clear();
		container.add(display.asWidget());
		updateContent();
		bind();
		
		
	}
	
	/**
	 * Bind.
	 */
	private void bind() {
		display.getPreviousLink().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				updateMeetings(display.getLastBeforeTime());
			}
			
		});
		
		display.getNextLink().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				updateMeetings(display.getBeforeTime());
			}
		});
		
		
		display.getDeleteLink().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				if(Window.confirm("Are you sure you want to delete this contact?")) {
					
					AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
						public void onFailure(Throwable caught) {
							eventBus.fireEvent(new DisplayInformationEvent("Unable to delete contact!", DisplayInformationEvent.Severity.FAILURE));
						}

						public void onSuccess(Boolean result) {
							eventBus.fireEvent(new DisplayInformationEvent("Contact successfully deleted!", DisplayInformationEvent.Severity.SUCCESS));
							History.newItem("browse");
						}
					};
					
					backboneRPC.deleteContact(display.getContact(), callback);
				}
			}
		});
		
		display.getEditLink().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				display.showUserEdit();
			}
		});
		
		display.getSaveEditLink().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				
				String name = display.getContactName().getText().trim();
				String email = display.getContactEmail().getText().trim();
				String workplace = display.getContactWorkplace().getText().trim();
				String workphone = display.getContactWorkphone().getText().trim();
				String cellphone = display.getContactCellphone().getText().trim();
				
				if(name.length() == 0) {
					Window.alert("Name cannot be blank!");
				} else {
					MyContact contact = display.getContact();
					MyContact newContact = new MyContact(user.getEmail(),name, email, cellphone, workphone, workplace, "");
					newContact.setId(contact.getId());
					
					AsyncCallback<MyContact> callback = new AsyncCallback<MyContact>() {
						public void onFailure(Throwable caught) {
							eventBus.fireEvent(new DisplayInformationEvent("Unable to save contact!", DisplayInformationEvent.Severity.FAILURE));
						}

						public void onSuccess(MyContact contact) {
							eventBus.fireEvent(new DisplayInformationEvent("Contact successfully saved!", DisplayInformationEvent.Severity.SUCCESS));
							display.setContact(contact);
							display.showUserDetails();
						}
						
					};
					
					
					backboneRPC.saveContact(newContact, callback);
					
				}
			}
		});
		
		display.getDeleteMeetingsLink().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				ArrayList<CheckBox> boxes = display.getCheckBoxes();
				for(int i=0; i<boxes.size(); i++) {
					if(boxes.get(i).getValue()) {
						long id = Long.parseLong(boxes.get(i).getElement().getId());
						AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {
							public void onFailure(Throwable caught) {
								eventBus.fireEvent(new DisplayInformationEvent("Unable to proceed with the request!", DisplayInformationEvent.Severity.FAILURE));
							}

							public void onSuccess(Boolean result) {
								eventBus.fireEvent(new DisplayInformationEvent("The meeting was successfully delete!", DisplayInformationEvent.Severity.SUCCESS));
							}
						};
						
						backboneRPC.deleteMeeting(id, callback);
					}
				}
				updateMeetings(0);
			}
		});
		
	}
	
	/**
	 * Main function to update the content of the container.
	 */
	public void updateContent() {
		
		
		// Fetch the contact
		AsyncCallback<MyContact> contactcallback = new AsyncCallback<MyContact>() {
			public void onFailure(Throwable caught) {
				eventBus.fireEvent(new DisplayInformationEvent("Unable to proceed with the request!", DisplayInformationEvent.Severity.FAILURE));
				
			}
			public void onSuccess(MyContact contact) {
				display.setContact(contact);
			}
		};
		
		backboneRPC.getById(Long.parseLong(this.parts[1]), contactcallback);
		
		this.updateMeetings(display.getBeforeTime());
		
	}
	
	/**
	 * Update meetings.
	 *
	 * @param beforeTime the before time
	 */
	private void updateMeetings(final int beforeTime) {
		// Fetch the contact's meetings
		AsyncCallback<ArrayList<MyMeeting>> callback = new AsyncCallback<ArrayList<MyMeeting>>() {
			public void onFailure(Throwable caught) {
			}

			public void onSuccess(final ArrayList<MyMeeting> meetings) {
				display.setData(meetings);
				if(meetings.size() > 0) {
					String userEmail = meetings.get(0).getOwner();
					long contactid = meetings.get(0).getContactId();
						
					
					// Get the navigation from this time
					AsyncCallback<ArrayList<Integer>> navigation_callback = new AsyncCallback<ArrayList<Integer>>() {
						public void onFailure(Throwable caught) {
							eventBus.fireEvent(new DisplayInformationEvent("Unable to fetch meetings!", DisplayInformationEvent.Severity.FAILURE));
						}
						public void onSuccess(ArrayList<Integer> navigation) {
							Integer previous = navigation.get(0);
							boolean next = false;
							if(navigation.get(1) == 1) {
								next = true;
							}
							
							display.updateNavigation(previous, next);
						}
					};
					backboneRPC.getMeetingsNavigation(userEmail, contactid, beforeTime, navigation_callback);
				}
				
			}
		};
		
		backboneRPC.getMeetings(this.user, Long.parseLong(this.parts[1]), beforeTime, callback);
		
	}
}

